﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
//
// DotNetNuke - http://www.dotnetnuke.com
// Copyright (c) 2002-2010
// by DotNetNuke Corporation
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System.Web.UI.WebControls;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Content;
using DotNetNuke.Entities.Content.Taxonomy;
using DotNetNuke.Security;
using DotNetNuke.Services.Localization;

namespace DotNetNuke.Web.UI.WebControls
{

	public class Tags : WebControl, IPostBackEventHandler, IPostBackDataHandler
	{

		public event EventHandler<EventArgs> TagsUpdated;

		#region "Private Members"

		private string _AddImageUrl;
		private bool _AllowTagging = false;
		private string _CancelImageUrl;
		private ContentItem _ContentItem;
		private string _NavigateUrlFormatString;
		private string _Separator = ",&nbsp;";
		private string _SaveImageUrl;
		private string _RepeatDirection = "Horizontal";
		private bool _ShowCategories;
		private bool _ShowTags;

		private string _Tags;
		private Vocabulary TagVocabulary
		{
			get {
				VocabularyController vocabularyController = new VocabularyController();
				return (from v in vocabularyController.GetVocabularies()
                       where v.IsSystem && v.Name == "Tags"
                       select v).SingleOrDefault();
			}
		}

		#endregion

		#region "Public Properties"

		public string AddImageUrl
		{
			get { return _AddImageUrl; }
			set { _AddImageUrl = value; }
		}

		public bool AllowTagging
		{
			get { return _AllowTagging; }
			set { _AllowTagging = value; }
		}

		public string CancelImageUrl
		{
			get { return _CancelImageUrl; }
			set { _CancelImageUrl = value; }
		}

		public ContentItem ContentItem
		{
			get { return _ContentItem; }
			set { _ContentItem = value; }
		}

		public bool IsEditMode
		{
			get
			{
				bool _IsEditMode = false;
				if (ViewState["IsEditMode"] != null)
				{
					_IsEditMode = Convert.ToBoolean(ViewState["IsEditMode"]);
				}
				return _IsEditMode;
			}
			set { ViewState["IsEditMode"] = value; }
		}

		public string NavigateUrlFormatString
		{
			get { return _NavigateUrlFormatString; }
			set { _NavigateUrlFormatString = value; }
		}

		public string RepeatDirection
		{
			get { return _RepeatDirection; }
			set { _RepeatDirection = value; }
		}

		public string SaveImageUrl
		{
			get { return _SaveImageUrl; }
			set { _SaveImageUrl = value; }
		}

		public string Separator
		{
			get { return _Separator; }
			set { _Separator = value; }
		}

		public bool ShowCategories
		{
			get { return _ShowCategories; }
			set { _ShowCategories = value; }
		}

		public bool ShowTags
		{
			get { return _ShowTags; }
			set { _ShowTags = value; }
		}

		#endregion

		#region "Private Methods"

		private string LocalizeString(string key)
		{
			string LocalResourceFile = Utilities.GetLocalResourceFile(this);
			string localizedString = null;
			if (!string.IsNullOrEmpty(key) && !string.IsNullOrEmpty(LocalResourceFile))
			{
				localizedString = Localization.GetString(key, LocalResourceFile);
			}
			else
			{
				localizedString = Null.NullString;
			}
			return localizedString;
		}

		private void RenderButton(HtmlTextWriter writer, string buttonType, string imageUrl)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Title, LocalizeString(string.Format("{0}.ToolTip", buttonType)));
			writer.AddAttribute(HtmlTextWriterAttribute.Href, Page.ClientScript.GetPostBackClientHyperlink(this, buttonType));
			writer.RenderBeginTag(HtmlTextWriterTag.A);

			//Image
			if (!string.IsNullOrEmpty(imageUrl))
			{
				writer.AddAttribute(HtmlTextWriterAttribute.Src, ResolveUrl(imageUrl));
				writer.RenderBeginTag(HtmlTextWriterTag.Img);
				writer.RenderEndTag();
			}

			writer.Write(LocalizeString(buttonType));
			writer.RenderEndTag();
		}

		private void RenderTerm(HtmlTextWriter writer, Term term, bool renderSeparator)
		{
			writer.AddAttribute(HtmlTextWriterAttribute.Href, string.Format(NavigateUrlFormatString, term.Name));
			writer.AddAttribute(HtmlTextWriterAttribute.Title, term.Name);
			writer.AddAttribute(HtmlTextWriterAttribute.Rel, "tag");
			writer.RenderBeginTag(HtmlTextWriterTag.A);
			writer.Write(term.Name);
			writer.RenderEndTag();

			if (renderSeparator)
			{
				writer.Write(Separator);
			}
		}

		private void SaveTags()
		{
			string tags = new PortalSecurity().InputFilter(_Tags, PortalSecurity.FilterFlag.NoMarkup | PortalSecurity.FilterFlag.NoScripting);
			tags = System.Web.HttpContext.Current.Server.HtmlEncode(tags);
			if (!string.IsNullOrEmpty(tags)) {
				foreach (string t in tags.Split(',')) {
					if (!string.IsNullOrEmpty(t)) {
                        string tagName = t.Trim(' ');
						Term existingTerm = (from term in ContentItem.Terms.AsQueryable()
                                             where term.Name.Equals(tagName, StringComparison.CurrentCultureIgnoreCase)
                                             select term).SingleOrDefault();

						if (existingTerm == null) {
							//Not tagged
							TermController termController = new TermController();
							Term term = (from te in termController.GetTermsByVocabulary(TagVocabulary.VocabularyId)
                                         where te.Name.Equals(tagName, StringComparison.CurrentCultureIgnoreCase)
										 select te).SingleOrDefault();
							if (term == null) {
								//Add term
								term = new Term(TagVocabulary.VocabularyId);
                                term.Name = tagName;
								termController.AddTerm(term);
							}

							//Add term to content
							ContentItem.Terms.Add(term);
							termController.AddTermToContent(term, ContentItem);
						}
					}
				}
			}

			IsEditMode = false;

			//Raise the Tags Updated Event
			OnTagsUpdate(EventArgs.Empty);
		}

		#endregion

		protected void OnTagsUpdate(EventArgs e)
		{
			if (TagsUpdated != null)
			{
				TagsUpdated(this, e);
			}
		}

		#region "Public Methods"

		protected override void OnPreRender(System.EventArgs e)
		{
			base.OnPreRender(e);

			if ((!this.Page.ClientScript.IsClientScriptBlockRegistered(this.UniqueID)))
			{
				StringBuilder sb = new StringBuilder();

				sb.Append("<script language='javascript' type='text/javascript' >");
				sb.Append(Environment.NewLine);
				sb.Append("function disableEnterKey(e)");
				sb.Append("{");
				sb.Append("var key;");
				sb.Append("if(window.event)");
				sb.Append("key = window.event.keyCode;");
				sb.Append("else ");
				sb.Append("key = e.which;");
				sb.Append("return (key != 13);");
				sb.Append("}");
				sb.Append("</script>");

				this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), this.UniqueID, sb.ToString());
			}

		}


		public override void RenderControl(HtmlTextWriter writer)
		{
			//Render Outer Div
			writer.AddAttribute(HtmlTextWriterAttribute.Class, RepeatDirection.ToLower());
			writer.RenderBeginTag(HtmlTextWriterTag.Div);

			//Render Categories
			if (ShowCategories) {
				//Render UL
				writer.AddAttribute(HtmlTextWriterAttribute.Class, "categories");
				writer.AddAttribute(HtmlTextWriterAttribute.Title, LocalizeString("Category.ToolTip"));
				writer.RenderBeginTag(HtmlTextWriterTag.Ul);

				//Render Category Links
				IEnumerable<Term> categories = (from cat in ContentItem.Terms
                                                where cat.VocabularyId != TagVocabulary.VocabularyId
                                                select cat);

				for (int i = 0; i <= categories.Count() - 1; i++) {
					if (i == 0) {
						//First Category
						writer.AddAttribute(HtmlTextWriterAttribute.Class, "first_tag");
					} else if (i == categories.Count() - 1) {
						//Last Category
						writer.AddAttribute(HtmlTextWriterAttribute.Class, "last_tag");
					}
					writer.RenderBeginTag(HtmlTextWriterTag.Li);

					RenderTerm(writer, categories.ToList()[i], i < categories.Count() - 1 && RepeatDirection.ToLower() == "horizontal");

					writer.RenderEndTag();
				}

				writer.RenderEndTag();

			}

			if (ShowTags) {
				//Render UL
				writer.AddAttribute(HtmlTextWriterAttribute.Class, "tags");
				writer.AddAttribute(HtmlTextWriterAttribute.Title, LocalizeString("Tag.ToolTip"));
				writer.RenderBeginTag(HtmlTextWriterTag.Ul);

				//Render Tag Links
				IEnumerable<Term> tags = (from cat in ContentItem.Terms
                                          where cat.VocabularyId == TagVocabulary.VocabularyId
                                          select cat);

				for (int i = 0; i <= tags.Count() - 1; i++) {
					if (i == 0) {
						//First Tag
						writer.AddAttribute(HtmlTextWriterAttribute.Class, "first_tag");
					} else if (i == tags.Count() - 1) {
						//Last Tag
						writer.AddAttribute(HtmlTextWriterAttribute.Class, "last_tag");
					}
					writer.RenderBeginTag(HtmlTextWriterTag.Li);

					RenderTerm(writer, tags.ToList()[i], i < tags.Count() - 1 && RepeatDirection.ToLower() == "horizontal");

					writer.RenderEndTag();
				}

				if (AllowTagging) {
					writer.RenderBeginTag(HtmlTextWriterTag.Li);

					if (IsEditMode) {
						writer.Write("&nbsp;&nbsp;");

						writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
						writer.AddAttribute("OnKeyPress", "return disableEnterKey(event)");
						writer.RenderBeginTag(HtmlTextWriterTag.Input);
						writer.RenderEndTag();

						writer.Write("&nbsp;&nbsp;");

						//Render Save Button
						RenderButton(writer, "Save", SaveImageUrl);

						writer.Write("&nbsp;&nbsp;");

						//Render Add Button
						RenderButton(writer, "Cancel", CancelImageUrl);
					} else {
						writer.Write("&nbsp;&nbsp;");

						//Render Add Button
						RenderButton(writer, "Add", AddImageUrl);
					}

					writer.RenderEndTag();
				}

				writer.RenderEndTag();

			}

			writer.RenderEndTag();

		}

		#endregion

		#region "IPostBackDataHandler Implementation"

		public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection)
		{
			_Tags = postCollection[postDataKey];

			return true;
		}


		public void RaisePostDataChangedEvent()
		{
		}

		#endregion

		#region "IPostBackEventHandler Implementation"

		public void RaisePostBackEvent(string eventArgument)
		{
			switch (eventArgument)
			{
				case "Add":
					IsEditMode = true;
					break;
				case "Cancel":
					IsEditMode = false;
					break;
				case "Save":
					SaveTags();
					break;
				default:
					IsEditMode = false;
					break;
			}
		}

		#endregion

	}

}

